package kline

import (
	"bbtradeByGo/pkg/email"
	db "bbtradeByGo/pkg/gmysql"
	"bbtradeByGo/pkg/logging"
	"database/sql"
	"fmt"
)

// Trade 获取交易中具体的值
type Trade struct {
	Id             int `json:"id"`
	CurrencyId     int `json:"currency_id"`
	BaseCurrencyId int `json:"base_currency_id"`
	CreateTime     int `json:"create_time"`
}

// TradePair 获取交易对的参数
type TradePair struct {
	Cid  int `json:"cid"`
	Bcid int `json:"bcid"`
}

// CensusTrade 统计trade值获取的结果
type CensusTrade struct {
	Time       int     `json:"time"`
	Id         int     `json:"id"`
	CreateTime int     `json:"create_time"`
	MaxPrice   float64 `json:"max_price"`
	MinPrice   float64 `json:"min_price"`
	SumNumber  float64 `json:"sum_number"`
	DescPrice  float64 `json:"desc_price"`
	AscPrice   float64 `json:"asc_price"`
}

// IDPosition id的位置
type IDPosition struct {
	IdDeal int `json:"id_deal"`
}

type RequireDataPrama struct {
	Bcid      int
	Cid       int
	EndTime   int
	StartTime int
	Period    int
	Tid       int
}

// RequireTradePair 获取交易对
func RequireTradePair() ([]*TradePair, error) {
	tradepair := make([]*TradePair, 0)
	err := db.DB.Unsafe().Select(&tradepair, `SELECT cid, bcid FROM abc_currency_pair`)
	if err != nil && err != sql.ErrNoRows {
		logging.Error("model.kline.RequireTradePair", err)
		email.SendMail("model.kline.RequireTradePair", err.Error())
		return nil, err
	}
	return tradepair, nil
}

// RequireIDPosition 获取正确的id位置（从哪个id开始）
func RequireIDPosition(period int) (*IDPosition, error) {
	WaitID := &IDPosition{}
	err := db.DB.Unsafe().Get(WaitID, `SELECT id_deal FROM abc_kline WHERE period = ? ORDER BY id_deal DESC LIMIT 1`, period)
	if err != nil && err != sql.ErrNoRows {
		logging.Error("model.kline.RequireIDPosition", err)
		email.SendMail("model.kline.RequireIDPosition", err.Error())
		return nil, err
	}
	return WaitID, nil
}

// RequireTradeData 获取交易的数据	
func RequireTradeData(uid int) ([]*Trade, error) {
	trades := make([]*Trade, 0)
	err := db.DB.Unsafe().Select(&trades, `SELECT * FROM abc_trade WHERE id > ? AND is_del = 0 ORDER BY id ASC`, uid)
	if err != nil && err != sql.ErrNoRows {
		logging.Error("model.kline.RequireTradeData", err)
		email.SendMail("model.kline.RequireTradeData", err.Error())
		return nil, err
	}
	return trades, nil
}

// RequireDataToKLine 获取数据并导入到kline表中
func RequireDataToKLine(period, cid, bcid int) {
	IDS, err := RequireIDPosition(period)
	logging.Info("require IDS value id ", IDS.IdDeal)
	if err != nil {
		logging.Error("model.kline.RequireIDPosition", err)
		email.SendMail("model.kline.RequireIDPosition", err.Error())
	}
	// 获取具体的trade值
	var id = 0
	if IDS != nil {
		id = IDS.IdDeal
	}

	trades, err := RequireTradeData(id)
	logging.Info("require trades success !")
	if err != nil {
		logging.Error("model.kline.RequireTradeData", err)
		email.SendMail("model.kline.RequireTradeData", err.Error())
	}
	// 赋值
	if len(trades) == 0{return}
	
	rp := &RequireDataPrama{
		Cid:       cid,
		Bcid:      bcid,
		Period:    period,
		StartTime: trades[0].CreateTime,
		EndTime:   trades[len(trades)-1].CreateTime,
		Tid:       trades[len(trades)-1].Id,
	}

	// 获取需要的参数值
	v := RequireValue(rp)
	// 插入数据
	err = InsertToKLine(v, rp)
	if err != nil {
		logging.Error("model.kline.InsertToKLine", err)
		email.SendMail("model.kline.InsertToKLine", err.Error())
	}
	logging.Info("insert kline data success !")
}

// RequireValue 根据不同的分钟数，获取对应的语句
func RequireValue(r *RequireDataPrama) []string {
	//根据时间，选择不同的查询参数
	var gb []string
	switch r.Period {
	case 1440:
		gb = []string{
			"(UNIX_TIMESTAMP(DATE_FORMAT(from_unixtime(create_time),'%Y-%m-%d'))) as time",
			"DATE_FORMAT(from_unixtime(create_time),'%Y-%m-%d')",
		}
	case 43200:
		gb = []string{
			"(UNIX_TIMESTAMP(DATE_FORMAT(from_unixtime(create_time),'%Y-%m'))) as time",
			"DATE_FORMAT(from_unixtime(create_time),'%Y-%m')",
		}
	default:
		gb = []string{
			fmt.Sprintf("FLOOR(MIN(create_time) / 60 / %d) * 60 * %d  AS time", r.Period, r.Period),
			fmt.Sprintf("TRUNCATE(create_time / %d / 60, 0)", r.Period),
		}
	}
	return gb
}

// InsertToKLine 插入数据到kline
func InsertToKLine(gb []string, r *RequireDataPrama) error {
	cs, err := RequireTradeCensusData(gb, r)
	if err != nil {
		logging.Error("model.kline.InsertToKLine", err)
		email.SendMail("model.kline.InsertToKLine", err.Error())
	}
	for _, c := range cs {
		// 这里abc_kline 要做联合索引
		if _, err := db.DB.Exec(`REPLACE INTO abc_kline (C, H, L, O, T, V, cid, bcid, period, timestamp, id_deal) VALUES (?,?,?,?,?,?,?,?,?,?,?)`,
			c.DescPrice, c.MaxPrice, c.MinPrice, c.AscPrice, c.Time, c.SumNumber, r.Cid, r.Bcid, r.Period, c.CreateTime, c.Id); err != nil {
			logging.Error("model.kline.InsertToKLine.REPLACE", err)
			email.SendMail("model.kline.InsertToKLine.REPLACE", err.Error())
			return err
		}
	}
	return nil
}

// RequireTradeCensusData 插入数据到kline
func RequireTradeCensusData(gb []string, r *RequireDataPrama) ([]*CensusTrade, error) {
	censustrade := make([]*CensusTrade, 0)
	SelectResult := fmt.Sprintf(`SELECT id,
	%s,
	create_time,
	MAX(price) AS max_price,
	MIN(price) AS min_price,
	SUM(number) AS sum_number,
	LEFT(GROUP_CONCAT(price ORDER BY id DESC),10) AS desc_price,
	LEFT(GROUP_CONCAT(price ORDER BY id ASC),10) AS asc_price
	FROM
		abc_trade
	WHERE
		create_time >= %d
	AND create_time < %d
	AND is_del = 0
	AND base_currency_id = %d
	AND currency_id = %d
	GROUP BY %s
	ORDER BY id ASC`, gb[0], r.StartTime, r.EndTime, r.Bcid, r.Cid, gb[1])

	err := db.DB.Unsafe().Select(&censustrade, SelectResult)
	if err != nil && err != sql.ErrNoRows {
		logging.Error("model.kline.RequireTradeCensusData", err)
		email.SendMail("model.kline.RequireTradeCensusData", err.Error())
		return nil, err
	}
	return censustrade, nil
}
